home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / advanced97 / billboard.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  7.8 KB  |  340 lines

  1. #include "stdlib.h"
  2. #include "stdio.h"
  3. #include "math.h"
  4. #include "texture.h"
  5. #include <GL/glut.h>
  6.  
  7. #ifndef __sgi
  8. /* Most math.h's do not define float versions of the trig functions. */
  9. #define sinf sin
  10. #define cosf cos
  11. #define atan2f atan2
  12. #endif
  13.  
  14. /* Some <math.h> files do not define M_PI... */
  15. #ifndef M_PI
  16. #define M_PI 3.14159265358979323846
  17. #endif
  18.  
  19. static int billboard = 1, texture = 1;
  20. static float scale = 1.;
  21. static float transx = 1.0, transy, rotx, roty;
  22. static int ox = -1, oy = -1;
  23. static int mot = 0;
  24. #define PAN    1
  25. #define ROT    2
  26.  
  27. void
  28. pan(const int x, const int y) {
  29.     transx +=  (x-ox)/500.;
  30.     transy -= (y-oy)/500.;
  31.     ox = x; oy = y;
  32.     glutPostRedisplay();
  33. }
  34.  
  35. void
  36. rotate(const int x, const int y) {
  37.     rotx += x-ox;
  38.     if (rotx > 360.) rotx -= 360.;
  39.     else if (rotx < -360.) rotx += 360.;
  40.     roty += y-oy;
  41.     if (roty > 360.) roty -= 360.;
  42.     else if (roty < -360.) roty += 360.;
  43.     ox = x; oy = y;
  44.     glutPostRedisplay();
  45. }
  46.  
  47. void
  48. motion(int x, int y) {
  49.     if (mot == PAN) pan(x, y);
  50.     else if (mot == ROT) rotate(x,y);
  51. }
  52.  
  53. void
  54. mouse(int button, int state, int x, int y) {
  55.     if(state == GLUT_DOWN) {
  56.     switch(button) {
  57.     case GLUT_LEFT_BUTTON:
  58.         mot = PAN;
  59.         motion(ox = x, oy = y);
  60.         break;
  61.     case GLUT_MIDDLE_BUTTON:
  62.         break;
  63.     case GLUT_RIGHT_BUTTON:
  64.         mot = ROT;
  65.         motion(ox = x, oy = y);
  66.         break;
  67.     }
  68.     } else if (state == GLUT_UP) {
  69.     mot = 0;
  70.     }
  71. }
  72.  
  73. void afunc(void) {
  74.     static int state;
  75.     if (state ^= 1) {
  76.     glAlphaFunc(GL_GREATER, .01);
  77.     glEnable(GL_ALPHA_TEST);
  78.     } else {
  79.     glDisable(GL_ALPHA_TEST);
  80.     }
  81. }
  82.  
  83. void demofunc(void) {
  84.     static float deltax = -.03;
  85.     static float deltay = 2.;
  86.  
  87.     transx += deltax;
  88.     if (transx > 2.0 || transx < -2.0) deltax = -deltax;
  89.  
  90.     rotx += deltay;
  91.     if (rotx > 360.f || rotx < 0.f) deltay = -deltay;
  92.     glutPostRedisplay();
  93. }
  94.  
  95. void dfunc(void) {
  96.     static int demo;
  97.     if (demo ^= 1) {
  98.     glutIdleFunc(demofunc);
  99.     } else {
  100.     glutIdleFunc(0);
  101.     }
  102. }
  103.  
  104. void bfunc(void) {
  105.     static int state;
  106.     if (state ^= 1) {
  107.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  108.     glEnable(GL_BLEND);
  109.     } else {
  110.     glDisable(GL_BLEND);
  111.     }
  112. }
  113.  
  114. void ffunc(void) {
  115.     billboard ^= 1;
  116. }
  117.  
  118. void tfunc(void) {
  119.     texture ^= 1;
  120. }
  121.  
  122. void up(void) { scale += .1; }
  123. void down(void) { scale -= .1; }
  124.  
  125. void help(void) {
  126.     printf("Usage: billboard [image]\n");
  127.     printf("'h'            - help\n");
  128.     printf("'a'            - toggle alpha test\n");
  129.     printf("'b'            - toggle blend\n");
  130.     printf("'d'            - toggle demo mode\n");
  131.     printf("'f'            - toggle fixed mode\n");
  132.     printf("'t'            - toggle texturing\n");
  133.     printf("'UP'           - scale up\n");
  134.     printf("'DOWN'         - scale down\n");
  135.     printf("left mouse     - pan\n");
  136.     printf("right mouse    - rotate\n");
  137. }
  138.  
  139. void init(char *filename) {
  140.     static unsigned *image;
  141.     static int width, height, components;
  142.     if (filename) {
  143.     image = read_texture(filename, &width, &height, &components);
  144.     if (image == NULL) {
  145.         fprintf(stderr, "Error: Can't load image file \"%s\".\n",
  146.             filename);
  147.         exit(EXIT_FAILURE);
  148.     } else {
  149.         printf("%d x %d image loaded\n", width, height);
  150.     }
  151.     if (components != 4) {
  152.         printf("must be an RGBA image\n");
  153.         exit(EXIT_FAILURE);
  154.     }
  155.     } else {
  156.     int i, j;
  157.     unsigned char *img;
  158.     components = 4; width = height = 256;
  159.     image = (unsigned *) malloc(width*height*sizeof(unsigned));
  160.     img = (unsigned char *)image;
  161.     for (j = 0; j < height; j++)
  162.         for (i = 0; i < width; i++) {
  163.         int w2 = width/2, h2 = height/2;
  164.         if ((i & 32) ^ (j & 32)) {
  165.             img[4*(i+j*width)+0] = 0xff;
  166.             img[4*(i+j*width)+1] = 0xff;
  167.             img[4*(i+j*width)+2] = 0xff;
  168.         } else {
  169.             img[4*(i+j*width)+0] = 0x0;
  170.             img[4*(i+j*width)+1] = 0x0;
  171.             img[4*(i+j*width)+2] = 0x0;
  172.         }
  173.         if ((i-w2)*(i-w2) + (j-h2)*(j-h2) > 64*64 &&
  174.             (i-w2)*(i-w2) + (j-h2)*(j-h2) < 300*300) img[4*(i+j*width)+3] = 0xff;
  175.         }
  176.  
  177.     }
  178.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  179.     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  180.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  181.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  182.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  183.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  184.     glTexImage2D(GL_TEXTURE_2D, 0, components, width, height, 0,
  185.          GL_RGBA, GL_UNSIGNED_BYTE, image);
  186.     glEnable(GL_TEXTURE_2D);
  187.     glMatrixMode(GL_PROJECTION);
  188.     glLoadIdentity();
  189.     gluPerspective(50.,1.,.1,10.);
  190.     glMatrixMode(GL_MODELVIEW);
  191.     glLoadIdentity();
  192.     glTranslatef(0.,0.,-5.5);
  193.     glClearColor(.25f, .25f, .25f, .25f);
  194.     glEnable(GL_DEPTH_TEST);
  195. }
  196.  
  197. static void calcMatrix(void);
  198.  
  199. void display(void) {
  200. #if NATE
  201.     float mat[16];
  202. #endif
  203.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  204.  
  205.     glLoadIdentity();
  206. #define RAD(x) (((x)*M_PI)/180.)
  207.     gluLookAt(-sinf(RAD(rotx))*5.5,transy,cosf(RAD(rotx))*5.5, 0.,0.,0., 0.,1.,0.);
  208.  
  209. #if NATE
  210.     glGetFloatv(GL_MODELVIEW_MATRIX, mat);
  211. #endif
  212.     /* floor */
  213.     glDisable(GL_TEXTURE_2D);
  214.     glColor4f(0.2, 0.8, 0.2, 1.);
  215.     glBegin(GL_POLYGON);
  216.     glVertex3f(-2.0, -1.0, -2.0);
  217.     glVertex3f( 2.0, -1.0, -2.0);
  218.     glVertex3f( 2.0, -1.0,  2.0);
  219.     glVertex3f(-2.0, -1.0,  2.0);
  220.     glEnd();
  221.  
  222.     glPushMatrix();
  223. #if 0
  224.     glTranslatef(transx, transy, 0.f);
  225.     glRotatef(rotx, 0., 1., 0.);
  226.     glRotatef(roty, 1., 0., 0.);
  227. #endif
  228.     glTranslatef(0.f, 0.f, -transx);
  229.     if (billboard) calcMatrix();
  230.     glScalef(scale,scale,1.);
  231.     if (texture) glEnable(GL_TEXTURE_2D);
  232.     glColor4f(1.f, 1.f, 1.f, 1.f);
  233.     glBegin(GL_POLYGON);
  234.     glTexCoord2f(0.0, 0.0);
  235.     glVertex2f(-1.0, -1.0);
  236.     glTexCoord2f(1.0, 0.0);
  237.     glVertex2f(1.0, -1.0);
  238.     glTexCoord2f(1.0, 1.0);
  239.     glVertex2f(1.0, 1.0);
  240.     glTexCoord2f(0.0, 1.0);
  241.     glVertex2f(-1.0, 1.0);
  242.     glEnd();
  243.     glPopMatrix();
  244.  
  245.     glutSwapBuffers();
  246. }
  247.  
  248. void reshape(int w, int h) {
  249.     glViewport(0, 0, w, h);
  250. }
  251.  
  252. /*ARGSUSED*/
  253. void
  254. key(unsigned char key, int x, int y) {
  255.     switch(key) {
  256.     case 'a': afunc(); break;
  257.     case 'd': dfunc(); break;
  258.     case 'b': bfunc(); break;
  259.     case 'f': ffunc(); break;
  260.     case 't': tfunc(); break;
  261.     case 'h': help(); break;
  262.     case '\033': exit(EXIT_SUCCESS); break;
  263.     default: break;
  264.     }
  265.     glutPostRedisplay();
  266. }
  267.  
  268. /*ARGSUSED*/
  269. void
  270. special(int key, int x, int y) {
  271.     switch(key) {
  272.     case GLUT_KEY_UP:    up(); break;
  273.     case GLUT_KEY_DOWN:    down(); break;
  274.     }
  275.     glutPostRedisplay();
  276. }
  277.  
  278. int main(int argc, char** argv) {
  279.     glutInitWindowSize(512, 512);
  280.     glutInit(&argc, argv);
  281.     glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);
  282.     (void)glutCreateWindow("billboard");
  283.     init(argv[1]);
  284.     glutDisplayFunc(display);
  285.     glutKeyboardFunc(key);
  286.     glutSpecialFunc(special);
  287.     glutReshapeFunc(reshape);
  288.     glutMouseFunc(mouse);
  289.     glutMotionFunc(motion);
  290.     glutMainLoop();
  291.     return 0;
  292. }
  293.  
  294. void
  295. buildRot(float theta, float x, float y, float z, float m[16]) {
  296.     float d = x*x + y*y + z*z;
  297.     float ct = cosf(RAD(theta)), st = sinf(RAD(theta));
  298.  
  299.     /* normalize */
  300.     if (d > 0) {
  301.     d = 1/d;
  302.     x *= d;
  303.     y *= d;
  304.     z *= d;
  305.     }
  306.  
  307.     m[ 0] = 1; m[ 1] = 0; m[ 2] = 0; m[ 3] = 0;
  308.     m[ 4] = 0; m[ 5] = 1; m[ 6] = 0; m[ 7] = 0;
  309.     m[ 8] = 0; m[ 9] = 0; m[10] = 1; m[11] = 0;
  310.     m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1;
  311.  
  312.     /* R = uu' + cos(theta)*(I-uu') + sin(theta)*S
  313.      *
  314.      * S =  0  -z   y    u' = (x, y, z)
  315.      *        z   0  -x
  316.      *       -y   x   0
  317.      */
  318.  
  319.      m[0] = x*x + ct*(1-x*x) + st*0;
  320.      m[4] = x*y + ct*(0-x*y) + st*-z;
  321.      m[8] = x*z + ct*(0-x*z) + st*y;
  322.  
  323.      m[1] = y*x + ct*(0-y*x) + st*z;
  324.      m[5] = y*y + ct*(1-y*y) + st*0;
  325.      m[9] = y*z + ct*(0-y*z) + st*-x;
  326.  
  327.      m[2] = z*x + ct*(0-z*x) + st*-y;
  328.      m[6] = z*y + ct*(0-z*y) + st*x;
  329.      m[10]= z*z + ct*(1-z*z) + st*0;
  330. }
  331.  
  332. static void
  333. calcMatrix(void) {
  334.     float mat[16];
  335.  
  336.     glGetFloatv(GL_MODELVIEW_MATRIX, mat);
  337.     buildRot(-180*atan2f(mat[8], mat[10])/M_PI, 0, 1, 0, mat);
  338.     glMultMatrixf(mat);
  339. }
  340.